﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics.Contracts;

namespace SimpleIR
{
	public abstract class IRValueType : IRType
	{
		protected IRValueType(string tnamespace, string tbasename, TypeQualifiers tqual)
			: base(tnamespace, tbasename, tqual)
		{
			Contract.Requires(!String.IsNullOrEmpty(tbasename));
		}

		public override void ProcessBuiltinInfoAsNeeded()
		{ ;}
	}

	/// <summary>
	/// A simple class to represent all structs (use diectly for most structs, enumerators and keyvalpairs are special cased).
	/// </summary>
	public class IRStructType : IRValueType
	{
		public IRStructType(string tnamespace, string tbasename, TypeQualifiers tqual)
			: base(tnamespace, tbasename, tqual)
		{
			Contract.Requires(!String.IsNullOrEmpty(tbasename));
		}
	}

	/// <summary>
	/// This class represents objects of type key/value pair.
	/// </summary>
	public sealed class IRKeyValuePairType : IRStructType
	{
		private IRMemberField m_keyfield;
		private IRMemberField m_valfield;

		public IRKeyValuePairType(string tnamespace, string tbasename, TypeQualifiers tqual)
			: base(tnamespace, tbasename, tqual)
		{
			Contract.Requires(!String.IsNullOrEmpty(tbasename));
		}

		public override void ProcessBuiltinInfoAsNeeded()
		{
			this.m_keyfield = this.TypeDescription.GetFieldWithNameDefIn("key");
			this.m_valfield = this.TypeDescription.GetFieldWithNameDefIn("value");
		}

		public IRMemberField KeyField
		{ get { return this.m_keyfield; } }

		public IRMemberField ValueField
		{ get { return this.m_valfield; } }
	}

	/// <summary>
	/// This class has the information needed for the enumerators
	/// </summary>
	public sealed class IREnumeratorType : IRStructType
	{
		/// <summary>
		/// This field contains the type that is returned by the enumerator.
		/// </summary>
		private readonly IRType m_enumovertype;

		/// <summary>
		/// The field that points to the collection the enumerator is processing.
		/// </summary>
		private IRMemberField m_enumtargetcollection;

		public IREnumeratorType(string tnamespace, string tbasename, TypeQualifiers tqual, IRType enumovertype)
			: base(tnamespace, tbasename, tqual)
		{
			Contract.Requires(!String.IsNullOrEmpty(tbasename));
			Contract.Requires(enumovertype != null);

			this.m_enumovertype = enumovertype;
			this.m_enumtargetcollection = null;
		}

		/// <summary>
		/// Return the type that this enumerator returns on the current calls.
		/// </summary>
		public IRType EnumOverType 
		{ 
			get 
			{
				Contract.Ensures(Contract.Result<IRType>() != null);

				return this.m_enumovertype;
			} 
		}

		/// <summary>
		/// Return the member field in this enumerator that points to the collection it is enumerating over.
		/// </summary>
		public IRMemberField EnumCollectionField
		{
			get
			{
				Contract.Ensures(Contract.Result<IRMemberField>() != null);

				return this.m_enumtargetcollection;
			}
		}

		public override void ProcessBuiltinInfoAsNeeded()
		{
			this.m_enumtargetcollection = this.TypeDescription.AllDefInFields.Find((IRMemberField mf) => mf.IsEnumeratorContainerTargetField);
		}
	}
}
